//
//  WXStickyTransformer.m
//  WXStickyTabView
//
//  Created by Zhiqiang Bao on 15-1-11.
//  Copyright (c) 2015年 Zhiqiang Bao. All rights reserved.
//

#import "WXStickyTransformer.h"
#import <objc/runtime.h>

@interface WXStickyTransformer () <UIScrollViewDelegate>

@end

@implementation WXStickyTransformer

+ (WXStickyTransformer *)defaultTransformer
{
    static WXStickyTransformer *deault = nil;
    
    if (deault == nil) {
        deault = [[WXStickyTransformer alloc] init];
    }
    
    return deault;
}

- (void)addSubviewsOn:(UIScrollView *)scrollView
     withTabBarHeader:(UIView *)tabBarHeader
            andTabBar:(UIView *)tabBar
{
    CGFloat width = scrollView.frame.size.width;
    CGFloat tabBarHeaderHeight = tabBarHeader.frame.size.height;
    CGFloat tabBarHeight = tabBar.frame.size.height;
    CGFloat viewHeight = tabBarHeight + tabBarHeaderHeight;
    
    UIView *viewHeader = [[UIView alloc] initWithFrame:CGRectMake(0, -viewHeight, width, viewHeight)];
    if (tabBarHeader) {
        [tabBarHeader removeFromSuperview];
        tabBarHeader.frame = CGRectMake(0, 0, width, tabBarHeaderHeight);
        [viewHeader addSubview:tabBarHeader];
    }
    
    if (tabBar) {
        [tabBar removeFromSuperview];
        tabBar.frame = CGRectMake(0, tabBarHeaderHeight, width, tabBarHeight);
        [viewHeader addSubview:tabBar];
    }
    
    [scrollView addSubview:viewHeader];
    
    UIEdgeInsets insets = scrollView.contentInset;
    insets.top = viewHeight;
    scrollView.contentInset = insets;
    
    viewHeader.tag = WXStickyViewTagTabBarContainer;
    tabBarHeader.tag = WXStickyViewTagTabBarHeader;
    tabBar.tag = WXStickyViewTagTabBar;
}

- (void)removeTagSubViewsOn:(UIScrollView *)scrollView
{
    UIView *container = [scrollView viewWithTag:WXStickyViewTagTabBarContainer];
    UIView *tabBarHeader = [container viewWithTag:WXStickyViewTagTabBarHeader];
    UIView *tabBar = [container viewWithTag:WXStickyViewTagTabBar]?:[scrollView.superview viewWithTag:WXStickyViewTagTabBar];
    
    UIEdgeInsets insets = scrollView.contentInset;
    insets.top = 0;
    scrollView.contentInset = insets;
    
    container.tag = 0;
    tabBarHeader.tag = 0;
    tabBar.tag = 0;
    [tabBar removeFromSuperview];
    [tabBarHeader removeFromSuperview];
    [container removeFromSuperview];
}

- (void)transformScrollView:(UIScrollView *)scrollView
           withTabBarHeader:(UIView *)tabBarHeader
                  andTabBar:(UIView *)tabBar
{
    [self removeTagSubViewsOn:scrollView];
    [self removeDelegateOnScrollView:scrollView];
    [self addSubviewsOn:scrollView withTabBarHeader:tabBarHeader andTabBar:tabBar];
    [self addDelegateOnScrollView:scrollView];
    [self swizzledScrollViewDidScroll:scrollView];
}

- (void)restoreScrollView:(UIScrollView *)scrollView
{
    [self removeTagSubViewsOn:scrollView];
    [self removeDelegateOnScrollView:scrollView];
}

- (void)addDelegateOnScrollView:(UIScrollView *)scrollView
{
    id delegate = scrollView.delegate;
    if (delegate == nil) {
        delegate = self;
    }
    
    Class class = [delegate class];
    
    SEL realSelector = @selector(scrollViewDidScroll:);
    SEL swizzledSelector = @selector(swizzledScrollViewDidScroll:);

    Method dumpMethod = class_getInstanceMethod([WXStickyTransformer class], @selector(dumpScrollViewDidScroll:));
    Method hookMethod = class_getInstanceMethod([WXStickyTransformer class], @selector(swizzledScrollViewDidScroll:));
    
    // add a dump selector first
    class_addMethod(class,
                    realSelector,
                    method_getImplementation(dumpMethod),
                    method_getTypeEncoding(dumpMethod));
    
    // add new scrollViewDidScroll: to delegate
    class_addMethod(class,
                    swizzledSelector,
                    method_getImplementation(hookMethod),
                    method_getTypeEncoding(hookMethod));
    
    
    // get the method of two classes
    Method originalMethod = class_getInstanceMethod(class, realSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    
    // exchange
    method_exchangeImplementations(originalMethod, swizzledMethod);
    
    // important: you need to reset the delegate of scrollview
    scrollView.delegate = nil;
    scrollView.delegate = delegate;
    
    // tag the scrollView if be swizzled
    scrollView.tag = WXStickyViewTagScrollView;
}

- (void)removeDelegateOnScrollView:(UIScrollView *)scrollView
{
    // it's been swizzled
    if (scrollView.tag == WXStickyViewTagScrollView) {
        [self addDelegateOnScrollView:scrollView];
        scrollView.tag = 0;
    }
}

- (void)dumpScrollViewDidScroll:(UIScrollView *)scrollView
{
    
}

- (void)swizzledScrollViewDidScroll:(UIScrollView *)scrollView
{
    if (scrollView.tag == WXStickyViewTagScrollView) {
        UIView *container = [scrollView viewWithTag:WXStickyViewTagTabBarContainer];
        UIView *tabBarHeader = [container viewWithTag:WXStickyViewTagTabBarHeader];
        UIView *tabBar = [container viewWithTag:WXStickyViewTagTabBar]?:[scrollView.superview viewWithTag:WXStickyViewTagTabBar];
        
        if (scrollView.contentOffset.y >= tabBarHeader.frame.size.height + container.frame.origin.y) {
            if ( tabBar.superview == container) {
                CGRect frame = tabBar.frame;
                frame.origin = scrollView.frame.origin;
                tabBar.frame = frame;
                
                [tabBar removeFromSuperview];
                [scrollView.superview addSubview:tabBar];
            }
        }else{
            if ( tabBar.superview != container) {
                CGFloat tabBarHeaderHeight = tabBarHeader.frame.size.height;
                
                CGRect frame = tabBar.frame;
                frame.origin = CGPointMake(0, tabBarHeaderHeight);
                tabBar.frame = frame;
                
                [tabBar removeFromSuperview];
                [container addSubview:tabBar];
            }
        }
    }
    
    [scrollView.delegate performSelector:@selector(swizzledScrollViewDidScroll:) withObject:scrollView];
}

@end
